package cn.chiship.framework.upms.biz.user.controller;


import cn.chiship.framework.common.annotation.SystemOptionAnnotation;
import cn.chiship.framework.common.enums.BusinessTypeEnum;
import cn.chiship.framework.upms.biz.user.entity.UpmsOrganization;
import cn.chiship.framework.upms.biz.user.entity.UpmsOrganizationExample;
import cn.chiship.framework.upms.biz.user.pojo.dto.*;
import cn.chiship.framework.upms.biz.user.service.UpmsOrganizationService;
import cn.chiship.framework.upms.biz.user.service.UpmsUserOrganizationService;
import cn.chiship.sdk.core.annotation.Authorization;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.base.constants.BaseConstants;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.framework.base.BaseController;
import cn.chiship.sdk.framework.base.BaseService;
import cn.chiship.sdk.framework.pojo.vo.TreeVo;
import cn.chiship.sdk.framework.util.FrameworkUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;

/**
 * 组织控制层
 * 2021/9/27
 *
 * @author lijian
 */
@RestController
@Authorization
@RequestMapping("/organization")
@Api(tags = "组织机构")
public class UpmsOrganizationController extends BaseController<UpmsOrganization, UpmsOrganizationExample> {

    private static final Logger LOGGER = LoggerFactory.getLogger(UpmsOrganizationController.class);

    @Resource
    private UpmsOrganizationService upmsOrganizationService;

    @Resource
    private UpmsUserOrganizationService upmsUserOrganizationService;

    @Override
    public BaseService getService() {
        return upmsOrganizationService;
    }

    @SystemOptionAnnotation(describe = "机构分页")
    @ApiOperation(value = "机构分页")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "sort", value = "排序方式", defaultValue = "-gmtModified", dataTypeClass = String.class, paramType = "query"),
            @ApiImplicitParam(name = "name", value = "机构名称", defaultValue = "", dataTypeClass = String.class, paramType = "query"),
            @ApiImplicitParam(name = "organizationCategory", value = "机构类型", defaultValue = "", dataTypeClass = String.class, paramType = "query"),

    })
    @GetMapping(value = "/treeTable")
    public ResponseEntity<BaseResult> treeTable(
            @RequestParam(required = false, defaultValue = "-gmtModified", value = "sort") String sort,
            @RequestParam(required = false, defaultValue = "", value = "name") String name,
            @RequestParam(required = false, defaultValue = "", value = "organizationCategory") String organizationCategory) {
        UpmsOrganizationExample upmsOrganizationExample = new UpmsOrganizationExample();
        /**
         * 创造条件
         */
        UpmsOrganizationExample.Criteria criteria = upmsOrganizationExample.createCriteria();
        criteria.andIsDeletedEqualTo(BaseConstants.NO);
        if (!StringUtil.isNullOrEmpty(name)) {
            criteria.andOrganizationNameLike("%" + name + "%");
        }
        if (!StringUtil.isNullOrEmpty(organizationCategory)) {
            criteria.andOrganizationCategoryEqualTo(organizationCategory);
        }
        /**
         * 排序
         */
        upmsOrganizationExample.setOrderByClause(FrameworkUtil.formatSort(sort));
        List<UpmsOrganization> organizations = upmsOrganizationService.selectByExample(upmsOrganizationExample);

        return super.responseEntity(BaseResult.ok(assemblyOrganizationTableTree("0", organizations)));
    }

    @ApiOperation(value = "根据父级加载机构")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pid", value = "父级", dataTypeClass = String.class, paramType = "query"),
    })
    @GetMapping(value = "/loadByPid")
    public ResponseEntity<BaseResult> loadByPid(@RequestParam(required = false, defaultValue = "0", value = "pid") String pid) {
        UpmsOrganizationExample upmsOrganizationExample = new UpmsOrganizationExample();
        /**
         * 创造条件
         */
        UpmsOrganizationExample.Criteria criteria = upmsOrganizationExample.createCriteria();
        criteria.andIsDeletedEqualTo(BaseConstants.NO).andPidEqualTo(pid);
        return super.responseEntity(BaseResult.ok(upmsOrganizationService.selectByExample(upmsOrganizationExample)));
    }


    @SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_SAVE, describe = "保存单位机构")
    @ApiOperation(value = "保存单位机构")
    @PostMapping(value = "saveUnit")
    public ResponseEntity<BaseResult> saveUnit(@RequestBody @Valid UpmsUnitDto upmsUnitDto) {

        UpmsOrganization upmsOrganization = new UpmsOrganization();
        BeanUtils.copyProperties(upmsUnitDto, upmsOrganization);
        upmsOrganization.setType(Byte.valueOf("1"));
        return super.responseEntity(super.save(upmsOrganization));

    }

    @SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE, describe = "更新单位机构")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键", required = true, dataTypeClass = String.class, paramType = "path"),
    })
    @ApiOperation(value = "更新单位机构")
    @PostMapping(value = "updateUnit/{id}")
    public ResponseEntity<BaseResult> updateUnit(@PathVariable("id") String id, @RequestBody @Valid UpmsUnitDto upmsUnitDto) {
        UpmsOrganization upmsOrganization = new UpmsOrganization();
        BeanUtils.copyProperties(upmsUnitDto, upmsOrganization);
        upmsOrganization.setType(Byte.valueOf("1"));
        return super.responseEntity(super.update(id, upmsOrganization));
    }

    @SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE, describe = "组织调整")
    @ApiOperation(value = "组织调整")
    @PostMapping(value = "adjustment")
    public ResponseEntity<BaseResult> adjustment(@RequestBody @Valid UpmsOrganizationAdjustmentDto organizationAdjustmentDto) {
        return super.responseEntity(upmsOrganizationService.adjustment(organizationAdjustmentDto.getOrganizationId(), organizationAdjustmentDto.getTargetOrganizationId()));
    }

    @ApiImplicitParams({
            @ApiImplicitParam(name = "type", value = "机构类型(1:机构   2:部门)", defaultValue = "1", dataTypeClass = Byte.class, paramType = "query"),
            @ApiImplicitParam(name = "pid", value = "父级", defaultValue = "0", dataTypeClass = String.class, paramType = "query"),
    })
    @SystemOptionAnnotation(describe = "生成组织机构编码")
    @ApiOperation(value = "生成组织机构编码")
    @GetMapping(value = "generateOrgCode")
    public ResponseEntity<BaseResult> generateOrgCode(@RequestParam(value = "pid") String pid,
                                                      @RequestParam(value = "type") Byte type) {
        return super.responseEntity(upmsOrganizationService.generateOrgCode(pid, type));
    }

    @SystemOptionAnnotation(describe = "生成邀请码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键", required = true, dataTypeClass = String.class, paramType = "path"),
    })
    @ApiOperation(value = "生成邀请码")
    @GetMapping(value = "invitationCode/{id}")
    public ResponseEntity<BaseResult> invitationCode(@PathVariable("id") String id) {
        return super.responseEntity(upmsOrganizationService.invitationCode(id));
    }

    @SystemOptionAnnotation(describe = "根据邀请码获取机构信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "邀请码", required = true, dataTypeClass = String.class, paramType = "path"),
    })
    @ApiOperation(value = "根据邀请码获取机构信息")
    @PostMapping(value = "getByInvitation/{code}")
    public ResponseEntity<BaseResult> getByInvitation(@PathVariable("code") String code) {
        return super.responseEntity(upmsOrganizationService.getByInvitation(code));
    }

    //-----------------------------部门相关开始----------------------------------

    @SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_SAVE, describe = "保存单位部门")
    @ApiOperation(value = "保存单位部门")
    @PostMapping(value = "saveDept")
    public ResponseEntity<BaseResult> saveDept(@RequestBody @Valid UpmsDepartmentDto upmsDepartmentDto) {
        UpmsOrganization upmsOrganization = new UpmsOrganization();
        BeanUtils.copyProperties(upmsDepartmentDto, upmsOrganization);
        upmsOrganization.setType(Byte.valueOf("2"));
        return super.responseEntity(super.save(upmsOrganization));
    }

    @SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_UPDATE, describe = "更新单位部门")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "主键", required = true, dataTypeClass = String.class, paramType = "path"),
    })
    @ApiOperation(value = "更新单位部门")
    @PostMapping(value = "updateDept/{id}")
    public ResponseEntity<BaseResult> update(@PathVariable("id") String id, @RequestBody @Valid UpmsDepartmentDto upmsDepartmentDto) {

        UpmsOrganization upmsOrganization = new UpmsOrganization();
        BeanUtils.copyProperties(upmsDepartmentDto, upmsOrganization);
        upmsOrganization.setId(id);
        upmsOrganization.setType(Byte.valueOf("2"));
        return super.responseEntity(super.update(id, upmsOrganization));
    }

    @SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_REMOVE, describe = "删除数据")
    @ApiOperation(value = "删除数据")
    @PostMapping(value = "remove")
    public ResponseEntity<BaseResult> remove(@RequestBody @Valid List<String> ids) {
        UpmsOrganizationExample upmsOrganizationExample = new UpmsOrganizationExample();
        upmsOrganizationExample.createCriteria().andIdIn(ids);
        return super.responseEntity(super.remove(upmsOrganizationExample));
    }

    @ApiOperation(value = "获取组织结构(统一为TreeVo)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pid", value = "父级", defaultValue = "0", dataTypeClass = String.class, paramType = "query"),
            @ApiImplicitParam(name = "category", value = "机构类型", dataTypeClass = String.class, paramType = "query"),
            @ApiImplicitParam(name = "type", value = "机构分类", dataTypeClass = Byte.class, paramType = "query"),
    })
    @GetMapping(value = "loadOrganizationTree")
    public ResponseEntity<BaseResult> loadOrganizationTree(
            @RequestParam(required = false, defaultValue = "", value = "category") String category,
            @RequestParam(required = false, defaultValue = "0", value = "pid") String pid,
            @RequestParam(required = false, defaultValue = "", value = "type") Byte type) {
        UpmsOrganizationExample organizationExample = new UpmsOrganizationExample();
        UpmsOrganizationExample.Criteria criteria = organizationExample.createCriteria().andIsDeletedEqualTo(BaseConstants.NO);

        if (!StringUtil.isNullOrEmpty(category)) {
            criteria.andOrganizationCategoryLike(category + ":%");
        }
        if (!StringUtil.isNull(type)) {
            criteria.andTypeEqualTo(type);
        }

        organizationExample.setOrderByClause(FrameworkUtil.formatSort("-gmtModified"));
        List<UpmsOrganization> organizations = upmsOrganizationService.selectByExample(organizationExample);
        List<TreeVo> treeVos = assemblyOrganization(pid, organizations);

        return super.responseEntity(BaseResult.ok(treeVos));
    }

    @SystemOptionAnnotation(option = BusinessTypeEnum.SYSTEM_OPTION_SAVE, describe = "组织添加用户")
    @ApiOperation(value = "设置负责人")
    @PostMapping(value = "setChargePerson")
    public ResponseEntity<BaseResult> setChargePerson(@RequestBody @Valid UpmsOrganizationChargePersonDto organizationChargePersonDto) {
        return super.responseEntity(upmsOrganizationService.setChargePerson(
                organizationChargePersonDto.getOrganizationId(),
                organizationChargePersonDto.getUserId(),
                organizationChargePersonDto.getRealName()));
    }

    private List<JSONObject> assemblyOrganizationTableTree(String pid, List<UpmsOrganization> organizations) {
        List<JSONObject> treeVos = new ArrayList<>();
        for (UpmsOrganization organization : organizations) {
            List<String> pids = Arrays.asList(organization.getPid().split(";"));
            if (pids.contains(pid)) {
                treeVos.add(JSON.parseObject(JSON.toJSONString(organization)));
            }
        }
        for (JSONObject treeVo : treeVos) {
            List<JSONObject> children = assemblyOrganizationTableTree(treeVo.getString("id"), organizations);
            if (!children.isEmpty()) {
                treeVo.put("children", children);
            }
        }
        return treeVos;
    }

    private List<TreeVo> assemblyOrganization(String pid, List<UpmsOrganization> organizations) {
        List<TreeVo> treeVos = new ArrayList<>();
        for (UpmsOrganization organization : organizations) {
            List<String> pids = Arrays.asList(organization.getPid().split(";"));
            if (pids.contains(pid)) {
                TreeVo treeVo = new TreeVo();
                treeVo.setId(organization.getId());
                treeVo.setLeaf(false);
                treeVo.setLabel(organization.getOrganizationName());
                treeVo.setExt(StringUtil.getString(organization.getType()));
                treeVo.setExt1(pid);
                treeVos.add(treeVo);
            }
        }
        for (int i = 0; i < treeVos.size(); i++) {
            List<TreeVo> children = assemblyOrganization(treeVos.get(i).getId(), organizations);
            Collections.sort(children, new Comparator<TreeVo>() {
                @Override
                public int compare(TreeVo o1, TreeVo o2) {
                    Byte type1 = Byte.parseByte(o1.getExt().split(":")[0]);
                    Byte type2 = Byte.parseByte(o2.getExt().split(":")[0]);
                    if (type1 > type2) {
                        return 1;
                    } else if (type1 < type2) {
                        return -1;
                    } else {
                        return 0;
                    }
                }
            });
            treeVos.get(i).setChildren(children);
            if (treeVos.get(i).getChildren().isEmpty()) {
                treeVos.get(i).setLeaf(true);
            }
        }
        return treeVos;
    }


}
